#pragma once
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <iostream>
#include <string>
#include <string.h>
#include <stack>
#include <queue>
#include <functional>
#include <unordered_map>
#include "task.h"
template <typename T>
class ThreadPool
{
public:
    int num_;
    std::queue<T> q;
    std::vector<std::thread> vec;
    std::mutex mtx;
    std::condition_variable cv;

public:
    ThreadPool(int num = 5) : num_(num)
    {
        vec.resize(num);
        for (int i = 0; i < num_; ++i)
        {
            vec[i] = std::thread(Routine, this);
        }
    }
    ~ThreadPool()
    {
        for (int i = 0; i < 5; ++i)
            vec[i].join();
    }

public:
    bool IsEmpty()
    {
        return q.empty();
    }
    static void Routine(ThreadPool<T> *const tp)
    {
        while (1)
        {
            std::unique_lock<std::mutex> ul(tp->mtx);
            while (tp->IsEmpty())
                tp->cv.wait(ul);

            T task = tp->q.front();
            tp->q.pop();
            ul.unlock();
            int fd = task.fd_;
            while (1)
            {
                char buf[128];
                std::vector<std::string> msg;
                int len = recv(fd,buf,128,0);
                if(len == 0)
                {
                    std::cout << "fd :" << fd << "关闭" << std::endl;
                    close(fd);
                    break;
                }
                memcpy(&task,buf,sizeof(T));
                memcpy(buf, task.buf, 64);
                char *token = nullptr;
                token = strtok(buf, " ");
                while (token != nullptr)
                {
                    msg.push_back(std::string(token));
                    token = strtok(nullptr, " ");
                }

                std::unordered_map<std::string,std::function<int(int, int)>> umap =
                    {
                        {"+", [](int a, int b) -> int
                         { return a + b; }},
                        {"-", [](int a, int b) -> int
                         { return a - b; }},
                        {"*", [](int a, int b) -> int
                         { return a * b; }},
                        {"/", [](int a, int b) -> int
                         { return a / b; }}};
                std::stack<int> st;
                for (auto &str : msg)
                {
                    if (str == "+" || str == "-" || str == "*" || str == "/")
                    {
                        int num2 = st.top();
                        st.pop();
                        int num1 = st.top();
                        st.pop();
                        st.push(umap[str](num1, num2));
                    }
                    else
                    {
                        st.push(atoi(str.c_str()));
                        std::cout << "push : " << str << std::endl;
                    }
                }

                int ret = st.top();
                char tmp[4];
                memcpy(tmp, &ret, 4);
                send(fd, tmp, 4, 0);
            }
        }
    }
    void Push(T task)
    {
        std::unique_lock<std::mutex> ul(mtx);
        q.push(task);
        cv.notify_one();
    }
};
